home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Pascal / Games / On The Edge 3.0.1p / On The Edge.p < prev    next >
Encoding:
Text File  |  1996-02-22  |  17.0 KB  |  811 lines  |  [TEXT/PJMM]

  1. { On the Edge}
  2. {}
  3. {This is an extremely simple card game written by John Stiles. It is one of the smallest games}
  4. {I've ever seen - 11k on disk after John added more color support - and is still a well-behaved}
  5. {Mac application. I'd say that makes it an excellent demo to build games and other programs on.}
  6. {The only problem was that John wrote it in C, but that weakness was easily fixed.}
  7.  
  8. program OnTheEdge;
  9.  
  10.     const
  11.         Empty = $FF;
  12.  
  13.         mApple = 128;
  14.         mFile = 129;
  15.         mEdit = 130;
  16.         iAbout = 1;
  17.         iPlay = 1;
  18.         iHelp = 2;
  19.         iQuit = 4;
  20.         iYes = 1;
  21.         iNo = 2;
  22.  
  23.         msgSelectMultOf10 = 1;
  24.         msgGameOver = 2;
  25.         msgYouWin = 3;
  26.  
  27.         Jack = 11;
  28.         Queen = 12;
  29.         King = 13;
  30.  
  31.     function FindSuit (card: Integer): Integer;
  32.     begin
  33.         FindSuit := BitAnd(card, 3);
  34.     end;
  35.  
  36.     function FindValue (card: Integer): Integer;
  37.     begin
  38.         FindValue := BSR(card, 2) + 1;
  39.     end;
  40.  
  41.     var
  42.         myWindow: WindowPtr;
  43.         suits: Handle;
  44.         deck: array[0..51] of Byte;
  45.         grid: array[0..3, 0..3] of Byte;
  46.         multiple: array[0..3, 0..3] of Boolean;
  47.         deckPos: Byte;
  48.         finished, gameInProgress, selectingMultiples: Boolean;
  49.         colorQDAvail: Boolean;
  50.         litGray, midGray, drkGray: RGBColor;
  51.  
  52.     function MakeRGBColor (r, g, b: Integer): RGBColor;
  53.     begin
  54.         MakeRGBColor.red := r;
  55.         MakeRGBColor.green := g;
  56.         MakeRGBColor.blue := b;
  57.     end;
  58.  
  59.     function RandomBefore (what: Integer): Integer;
  60.         var
  61.             randomVal: Integer;
  62.     begin
  63.         randomVal := Random;
  64.  
  65.         if (randomVal < 0) then
  66.             randomVal := -randomVal;
  67.  
  68.         randomVal := randomVal mod what;
  69.  
  70.         RandomBefore := randomVal;
  71.  
  72.     {And what's wrong with RandomBefore := Abs(Random) mod what; ?}
  73.     end; {RandomBefore}
  74.  
  75.     procedure Shuffle;
  76.         var
  77.             count, count2, swap, temp: Integer;
  78.     begin
  79.         deckPos := 0;
  80.  
  81.         for count := 0 to 51 do
  82.             begin
  83.                 deck[count] := count;
  84.             end;
  85.  
  86.         for count2 := 1 to 20 do
  87.             begin
  88.                 for count := 0 to 51 do
  89.                     begin
  90.                         swap := RandomBefore(52);
  91.                         temp := deck[count];
  92.                         deck[count] := deck[swap];
  93.                         deck[swap] := temp;
  94.                     end;
  95.             end;
  96.     end; {Shuffle}
  97.  
  98.     procedure EmptyGrid;
  99.         var
  100.             count, count2: Integer;
  101.     begin
  102.         for count := 0 to 3 do
  103.             begin
  104.                 for count2 := 0 to 3 do
  105.                     begin
  106.                         grid[count][count2] := Empty;
  107.                         multiple[count][count2] := false;
  108.                     end;
  109.             end;
  110.  
  111.         Shuffle;
  112.     end; {EmptyGrid}
  113.  
  114.     procedure LabelGrid (horiz: Integer; vert: Integer);
  115.         var
  116.             message: Str255;
  117.     begin
  118.         GetIndString(message, 129, (vert * 4) + horiz + 1);
  119.  
  120.         TextFont(geneva);
  121.         TextSize(9);
  122.  
  123.         if (colorQDAvail) then
  124.  
  125.             begin
  126.                 MoveTo(horiz * 64 + 21, vert * 64 + 37);
  127.                 ForeColor(whiteColor);
  128.                 DrawString(message);
  129.             end;
  130.  
  131.         MoveTo(horiz * 64 + 20, vert * 64 + 36);
  132.         ForeColor(redColor);
  133.         DrawString(message);
  134.     end; {LabelGrid}
  135.  
  136.     procedure OutlineButton (theDialog: DialogPtr; which: Integer);
  137.         var
  138.             itemType: Integer;
  139.             itemHandle: Handle;
  140.             itemRect: Rect;
  141.     begin
  142.         GetDItem(theDialog, which, itemType, itemHandle, itemRect);
  143.         InsetRect(itemRect, -4, -4);
  144.         PenSize(3, 3);
  145.         FrameRoundRect(itemRect, 16, 16);
  146.     end; {OutlineButton}
  147.  
  148.     procedure DrawSICN (var destRect: Rect; SICNhandle: Handle; which: Integer);
  149.         var
  150.             myBitMap: BitMap;
  151.             srcRect: Rect;
  152.     begin
  153.         SetRect(srcRect, 0, 0, 16, 16);
  154.         HLock(SICNhandle);
  155.  
  156.         myBitMap.rowBytes := 2;
  157.         myBitMap.bounds := srcRect;
  158.         myBitMap.baseAddr := Ptr(Longint(SICNhandle^) + (which * 32));
  159.  
  160.         CopyBits(myBitMap, myWindow^.portBits, srcRect, destRect, srcCopy, nil);
  161.  
  162.         HUnlock(SICNhandle);
  163.     end; {DrawSICN}
  164.  
  165.     procedure DrawBWCard (var myRectP: Rect; mySuit: Integer; myValue: Integer);
  166.         var
  167.             myRect: Rect;
  168.             disp: Str255;
  169.     begin
  170.         disp := 'A 2 3 4 5 6 7 8 9 10J Q K ';
  171.         myRect := myRectP;
  172.  
  173.         InsetRect(myRect, 10, 5);
  174.  
  175.         if (myValue <= 13) then
  176.             begin
  177.                 FrameRoundRect(myRect, 8, 8);
  178.  
  179.                 TextFont(geneva);
  180.                 TextSize(12);
  181.                 MoveTo(myRect.left + 4, myRect.top + 15);
  182.                 DrawText(@disp[1], (myValue - 1) * 2, 2);
  183.  
  184.                 myRect.bottom := myRect.bottom - 5;
  185.                 myRect.right := myRect.right - 5;
  186.                 myRect.top := myRect.bottom - 16;
  187.                 myRect.left := myRect.right - 16;
  188.  
  189.                 if mySuit <= 1 then
  190.                     ForeColor(redColor)
  191.                 else
  192.                     ForeColor(blackColor);
  193.                 DrawSICN(myRect, suits, mySuit);
  194.             end;
  195.     end; {DrawBWCard}
  196.  
  197.     procedure DrawColorCard (var myRectP: Rect; mySuit: Integer; myValue: Integer);
  198.         var
  199.             myRect: Rect;
  200.             disp: Str255;
  201.             myRegion, tempRegion: RgnHandle;
  202.  
  203.     begin
  204.         disp := 'A 2 3 4 5 6 7 8 9 10J Q K ';
  205.         myRect := myRectP;
  206.  
  207.         InsetRect(myRect, 10, 5);
  208.  
  209.         if (myValue <= 13) then
  210.             begin
  211.                 ForeColor(blackColor);
  212.                 FrameRoundRect(myRect, 8, 8);
  213.                 InsetRect(myRect, 1, 1);
  214.                 RGBForeColor(midGray);
  215.                 PaintRoundRect(myRect, 8, 8);
  216.  
  217.  
  218.                 ForeColor(whiteColor);
  219.                 FrameRoundRect(myRect, 8, 8);
  220.                 InsetRect(myRect, 1, 1);
  221.                 FrameRoundRect(myRect, 8, 8);
  222.  
  223.                 tempRegion := NewRgn;
  224.                 myRegion := NewRgn;
  225.                 GetClip(tempRegion);
  226.  
  227.                 OpenRgn;
  228.                 MoveTo(myRect.right + 1, myRect.top);
  229.                 LineTo(myRect.left, myRect.bottom + 1);
  230.                 LineTo(myRect.right + 1, myRect.bottom + 1);
  231.                 LineTo(myRect.right + 1, myRect.top);
  232.                 CloseRgn(myRegion);
  233.                 SetClip(myRegion);
  234.                 RGBForeColor(drkGray);
  235.                 FrameRoundRect(myRect, 8, 8);
  236.                 InsetRect(myRect, -1, -1);
  237.                 FrameRoundRect(myRect, 8, 8);
  238.  
  239.                 SetClip(tempRegion);
  240.                 DisposeRgn(myRegion);
  241.                 DisposeRgn(tempRegion);
  242.  
  243.                 InsetRect(myRect, -1, -1);
  244.  
  245.                 TextFont(geneva);
  246.                 TextSize(12);
  247.  
  248.                 ForeColor(whiteColor);
  249.                 MoveTo(myRect.left + 5, myRect.top + 16);
  250.                 DrawText(@disp[1], (myValue - 1) * 2, 2);
  251.  
  252.                 ForeColor(blackColor);
  253.                 MoveTo(myRect.left + 4, myRect.top + 15);
  254.                 DrawText(@disp[1], (myValue - 1) * 2, 2);
  255.  
  256.                 myRect.bottom := myRect.bottom - 5;
  257.                 myRect.right := myRect.right - 5;
  258.                 myRect.top := myRect.bottom - 16;
  259.                 myRect.left := myRect.right - 16;
  260.  
  261.                 if mySuit <= 1 then
  262.                     ForeColor(redColor)
  263.                 else
  264.                     ForeColor(blackColor);
  265.                 RGBBackColor(midGray);
  266.                 DrawSICN(myRect, suits, mySuit);
  267.             end;
  268.     end; {DrawColorCard}
  269.  
  270.     procedure DrawCard (card: Byte; horiz: Integer; vert: Integer);
  271.         var
  272.             myRect: Rect;
  273.             mySuit, myValue: Byte;
  274.     begin
  275.         myRect.top := vert * 64;
  276.         myRect.bottom := myRect.top + 64;
  277.         myRect.left := horiz * 64;
  278.         myRect.right := myRect.left + 64;
  279.  
  280.         mySuit := FindSuit(card);
  281.         myValue := FindValue(card);
  282.  
  283.         if (colorQDAvail) then
  284.             DrawColorCard(myRect, mySuit, myValue)
  285.         else
  286.             DrawBWCard(myRect, mySuit, myValue);
  287.     end; {DrawCard}
  288.  
  289.     procedure PromptMessage (messageID: Integer);
  290.         var
  291.             message: Str255;
  292.     begin
  293.         GetIndString(message, 128, messageID);
  294.  
  295.         SetPort(myWindow);
  296.         MoveTo(20, 290);
  297.         TextFont(systemFont);
  298.         TextSize(12);
  299.         ForeColor(blackColor);
  300.  
  301.         DrawString(message);
  302.     end; {PromptMessage}
  303.  
  304.     procedure ClearMessage;
  305.         var
  306.             myRect: Rect;
  307.     begin
  308.         SetRect(myRect, 0, 257, 256, 320);
  309.         BackColor(whiteColor);
  310.         EraseRect(myRect);
  311.     end; {ClearMessage}
  312.  
  313.     procedure DrawNewCard;
  314.         var
  315.             currentCard, cardValue: Integer;
  316.     begin
  317.         deckPos := deckPos + 1;
  318.         currentCard := deck[deckPos];
  319.         cardValue := FindValue(currentCard);
  320.         DrawCard(currentCard, 3, 4);
  321.  
  322.         if (((cardValue = King) and not ((grid[0][0] = Empty) or (grid[0][3] = Empty) or (grid[3][0] = Empty) or (grid[3][3] = Empty))) or ((cardValue = Queen) and not ((grid[1][0] = Empty) or (grid[2][0] = Empty) or (grid[1][3] = Empty) or (grid[2][3] = Empty))) or ((cardValue = Jack) and not ((grid[0][1] = Empty) or (grid[0][2] = Empty) or (grid[3][1] = Empty) or (grid[3][2] = Empty)))) then
  323.             begin
  324.                 gameInProgress := false;
  325.  
  326.                 PromptMessage(msgGameOver);
  327.             end;
  328.     end; {DrawNewCard}
  329.  
  330.     procedure DrawSquare (x: Integer; y: Integer);
  331.         var
  332.             myRect: Rect;
  333.     begin
  334.         myRect.top := y * 64;
  335.         myRect.bottom := myRect.top + 65;
  336.         myRect.left := x * 64;
  337.         myRect.right := myRect.left + 65;
  338.  
  339.         ForeColor(blueColor);
  340.         FrameRect(myRect);
  341.  
  342.         InsetRect(myRect, 1, 1);
  343.         if (colorQDAvail) then
  344.             begin
  345.                 RGBBackColor(litGray);
  346.                 EraseRect(myRect);
  347.                 ForeColor(whiteColor);
  348.                 FrameRect(myRect);
  349.  
  350.                 InsetRect(myRect, 1, 1);
  351.                 FrameRect(myRect);
  352.                 InsetRect(myRect, -1, -1);
  353.  
  354.                 RGBForeColor(drkGray);
  355.                 MoveTo(myRect.right - 1, myRect.top);
  356.                 LineTo(myRect.right - 1, myRect.bottom - 1);
  357.                 LineTo(myRect.left, myRect.bottom - 1);
  358.                 LineTo(myRect.left + 1, myRect.bottom - 2);
  359.                 LineTo(myRect.right - 2, myRect.bottom - 2);
  360.                 LineTo(myRect.right - 2, myRect.top + 1);
  361.             end
  362.         else
  363.             begin
  364.                 BackColor(whiteColor);
  365.                 EraseRect(myRect);
  366.             end;
  367.         InsetRect(myRect, -1, -1);
  368.  
  369.         if (grid[x][y] <> Empty) then
  370.             begin
  371.                 DrawCard(grid[x][y], x, y);
  372.                 if (multiple[x][y]) then
  373.                     begin
  374.                         myRect.top := (y * 64) + 10;
  375.                         myRect.left := (x * 64) + 30;
  376.                         myRect.bottom := myRect.top + 16;
  377.                         myRect.right := myRect.left + 16;
  378.  
  379.                         ForeColor(blueColor);
  380.  
  381.                         if (colorQDAvail) then
  382.                             RGBBackColor(midGray)
  383.                         else
  384.                             BackColor(whiteColor);
  385.  
  386.                         DrawSICN(myRect, suits, 4);
  387.                     end;
  388.             end
  389.         else
  390.             begin
  391.                 LabelGrid(x, y);
  392.             end;
  393.     end; {DrawSquare}
  394.  
  395.  
  396.     procedure FinishSelecting;
  397.         var
  398.             myRect: Rect;
  399.             count, count2: Integer;
  400.     begin
  401.         ClearMessage;
  402.  
  403.         for count := 0 to 3 do
  404.             begin
  405.                 for count2 := 0 to 3 do
  406.                     begin
  407.                         if (multiple[count][count2] = true) then
  408.                             begin
  409.                                 multiple[count][count2] := false;
  410.                                 DrawSquare(count, count2);
  411.                             end;
  412.  
  413.                         if (grid[count][count2] = Empty) then
  414.                             begin
  415.                                 selectingMultiples := false;
  416.                             end;
  417.                     end;
  418.             end;
  419.  
  420.         if (selectingMultiples) then
  421.             begin
  422.                 gameInProgress := false;
  423.                 selectingMultiples := false;
  424.  
  425.                 ClearMessage;
  426.                 PromptMessage(msgGameOver);
  427.  
  428.                 Exit(FinishSelecting);
  429.             end;
  430.  
  431.         DrawNewCard;
  432.     end; {FinishSelecting}
  433.  
  434.     procedure SelectMultiples (var wherePtr: Point);
  435.         var
  436.             myRect: Rect;
  437.             where: Point;
  438.             total, count, count2: Integer;
  439.     begin
  440.         total := 0;
  441.         where := wherePtr;
  442.  
  443.         where.h := BSR(where.h, 6);
  444.         where.v := BSR(where.v, 6);
  445.  
  446.         if (where.v > 3) then
  447.             begin
  448.                 FinishSelecting;
  449.                 Exit(SelectMultiples);
  450.             end;
  451.  
  452.         for count := 0 to 3 do
  453.             begin
  454.                 for count2 := 0 to 3 do
  455.                     begin
  456.                         if (multiple[count][count2]) then
  457.                             total := total + FindValue(grid[count][count2]);
  458.                     end;
  459.             end;
  460.  
  461.         if (multiple[where.h][where.v]) then
  462.             begin
  463.                 multiple[where.h][where.v] := false;
  464.                 DrawSquare(where.h, where.v);
  465.                 Exit(SelectMultiples);
  466.             end
  467.         else
  468.             begin
  469.                 total := total + FindValue(grid[where.h][where.v]);
  470.  
  471.                 if (total > 10) then
  472.                     Exit(SelectMultiples);
  473.  
  474.                 multiple[where.h][where.v] := true;
  475.                 DrawSquare(where.h, where.v);
  476.  
  477.                 if (total = 10) then
  478.                     for count := 0 to 3 do
  479.                         for count2 := 0 to 3 do
  480.                             if (multiple[count][count2]) then
  481.  
  482.                                 begin
  483.                                     grid[count][count2] := Empty;
  484.                                     multiple[count][count2] := false;
  485.  
  486.                                     DrawSquare(count, count2);
  487.                                 end;
  488.             end;
  489.     end; {SelectMultiples}
  490.  
  491.     procedure StartSelecting;
  492.     begin
  493.         ClearMessage;
  494.  
  495.         PromptMessage(msgSelectMultOf10);
  496.     end;
  497.  
  498.     procedure PlaceCards (var wherePtr: Point);
  499.         var
  500.             where: Point;
  501.             currentCard, cardValue: Byte;
  502.             count, count2: Integer;
  503.  
  504.     begin
  505.         where := wherePtr;
  506.  
  507.         where.h := BSR(where.h, 6);
  508.         where.v := BSR(where.v, 6);
  509.  
  510.         if (where.v > 3) then
  511.             Exit(PlaceCards);
  512.  
  513.         if (grid[where.h][where.v] <> Empty) then
  514.             Exit(PlaceCards);
  515.  
  516.         currentCard := deck[deckPos];
  517.         cardValue := FindValue(currentCard);
  518.  
  519. {These huge if's could use some rewriting to be truly efficient.}
  520.  
  521.         if ((cardValue = King) and not (((where.h = 0) or (where.h = 3)) and ((where.v = 0) or (where.v = 3)))) then
  522.             Exit(PlaceCards);
  523.  
  524.         if ((cardValue = Queen) and not (((where.h = 1) and (where.v = 0)) or ((where.h = 2) and (where.v = 0)) or ((where.h = 1) and (where.v = 3)) or ((where.h = 2) and (where.v = 3)))) then
  525.             Exit(PlaceCards);
  526.  
  527.         if ((cardValue = Jack) and not (((where.h = 0) and (where.v = 1)) or ((where.h = 0) and (where.v = 2)) or ((where.h = 3) and (where.v = 1)) or ((where.h = 3) and (where.v = 2)))) then
  528.             Exit(PlaceCards);
  529.  
  530.         grid[where.h][where.v] := currentCard;
  531.  
  532.         DrawCard(currentCard, where.h, where.v);
  533.  
  534.         if ((FindValue(grid[0][0]) = King) and (FindValue(grid[0][3]) = King) and (FindValue(grid[3][0]) = King) and (FindValue(grid[3][3]) = King) and (FindValue(grid[1][0]) = Queen) and (FindValue(grid[2][0]) = Queen) and (FindValue(grid[1][3]) = Queen) and (FindValue(grid[2][3]) = Queen) and (FindValue(grid[0][1]) = Jack) and (FindValue(grid[0][2]) = Jack) and (FindValue(grid[3][1]) = Jack) and (FindValue(grid[3][2]) = Jack)) then
  535.  
  536.             begin
  537.                 ClearMessage;
  538.  
  539.                 PromptMessage(msgYouWin);
  540.  
  541.                 gameInProgress := false;
  542.  
  543.                 Exit(PlaceCards);
  544.             end;
  545.  
  546.         selectingMultiples := true;
  547.         for count := 0 to 3 do
  548.             begin
  549.                 for count2 := 0 to 3 do
  550.                     begin
  551.                         if (grid[count][count2] = Empty) then
  552.                             selectingMultiples := false;
  553.                     end;
  554.             end;
  555.  
  556.         if (selectingMultiples) then
  557.             begin
  558.                 StartSelecting;
  559.                 Exit(PlaceCards);
  560.             end;
  561.  
  562.         DrawNewCard;
  563.     end;
  564.  
  565.     procedure RedrawWindow;
  566.         var
  567.             count, count2: Integer;
  568.             myRect: Rect;
  569.     begin
  570.         for count := 0 to 3 do
  571.             for count2 := 0 to 3 do
  572.                 DrawSquare(count2, count);
  573.  
  574.         if (selectingMultiples) then
  575.             PromptMessage(msgSelectMultOf10)
  576.         else if deckPos < 52 then
  577.             DrawCard(deck[deckPos], 3, 4)
  578.         else
  579.             DrawCard(Empty, 3, 4);
  580.  
  581.         if (not gameInProgress) then
  582.             PromptMessage(msgGameOver);
  583.     end; {RedrawWindow}
  584.  
  585.     procedure Initialize;
  586.         var
  587.             thisSysInfo: SysEnvRec;
  588.             err: OSErr;
  589.     begin
  590. {$IFC UNDEFINED THINK_PASCAL}
  591.         MaxApplZone;
  592.         MoreMasters;
  593.  
  594.         InitGraf(qd.thePort);
  595.         InitFonts;
  596.         FlushEvents(everyEvent, 0);
  597.         InitWindows;
  598.         InitMenus;
  599.         TEInit;
  600.         InitDialogs(nil);
  601.         InitCursor;
  602. {$ENDC}
  603.  
  604. { GetDateTime( (unsigned long * ) & randSeed ) ); / / seed the random #    generator }
  605.         GetDateTime(randSeed);
  606. {was: GetDateTime( (LongInt ^)LMGetRndSeed );}
  607.  
  608.         err := SysEnvirons(curSysEnvVers, thisSysInfo);
  609.         colorQDAvail := thisSysInfo.hasColorQD;
  610.  
  611.         litGray := MakeRGBColor($E000, $E000, $E000);
  612.         midGray := MakeRGBColor($D000, $D000, $D000);
  613.         drkGray := MakeRGBColor($A000, $A000, $A000);
  614.     end; {Initialize}
  615.  
  616.     procedure RetrieveResources;
  617.         var
  618.             count: Integer;
  619.             menuBar: Handle;
  620.             menu: MenuHandle;
  621.  
  622.     { menus}
  623.  
  624.     begin
  625.         menuBar := GetNewMBar(128);
  626.         if (menuBar = nil) then
  627.             begin
  628.                 SysBeep(1);
  629.                 ExitToShell;
  630.             end;
  631.  
  632.         SetMenuBar(menuBar);
  633.  
  634.         menu := GetMHandle(mApple);
  635.         AddResMenu(menu, 'DRVR');
  636.  
  637.         DrawMenuBar;
  638.  
  639.     { window}
  640.  
  641.         if (colorQDAvail) then
  642.             myWindow := GetNewCWindow(128, nil, WindowPtr(-1))
  643.         else
  644.             myWindow := GetNewWindow(128, nil, WindowPtr(-1));
  645.  
  646.         if (myWindow = nil) then
  647.             begin
  648.                 SysBeep(1);
  649.                 ExitToShell;
  650.             end;
  651.         ShowWindow(myWindow);
  652.         SetPort(myWindow);
  653.  
  654.     { suit SICNs}
  655.  
  656.         suits := GetResource('SICN', 128);
  657.     end;
  658.  
  659.     procedure StartGame;
  660.         var
  661.             myDialog: DialogPtr;
  662.             response: Integer;
  663.     begin
  664.         if gameInProgress then
  665.             begin
  666.                 myDialog := GetNewDialog(129, nil, WindowPtr(-1));
  667.  
  668.                 ShowWindow(myDialog);
  669.                 SetPort(myDialog);
  670.  
  671.                 OutlineButton(myDialog, iYes);
  672.  
  673.                 ModalDialog(nil, response);
  674.  
  675.                 DisposDialog(myDialog);
  676.  
  677.                 if (response = iNo) then
  678.                     Exit(StartGame);
  679.             end;
  680.  
  681.         gameInProgress := true;
  682.  
  683.         selectingMultiples := false;
  684.  
  685.         EmptyGrid;
  686.  
  687.         SetPort(myWindow);
  688.         BackColor(whiteColor);
  689.         EraseRect((myWindow^.portRect));
  690.         RedrawWindow;
  691.     end; {StartGame}
  692.  
  693.     procedure HandleMenus (selection: LongInt);
  694.         var
  695.             menu, item, i: Integer;
  696.             appleMenu: MenuHandle;
  697.             deskAccessory: Str255;
  698.     begin
  699.         menu := BSR(selection, 16);
  700.         item := selection;
  701.         case menu of
  702.             mApple: 
  703.                 if (item = iAbout) then
  704.                     begin
  705.                         i := Alert(128, nil);
  706.                     end
  707.                 else
  708.                     begin
  709.                         appleMenu := GetMHandle(mApple);
  710.                         GetItem(appleMenu, item, deskAccessory);
  711.                         i := OpenDeskAcc(deskAccessory);
  712.                     end;
  713.  
  714.             mFile: 
  715.                 case item of
  716.                     iPlay: 
  717.                         StartGame;
  718.                     iHelp: 
  719.                         begin
  720.                             i := Alert(130, nil);
  721.                             i := Alert(131, nil);
  722.                         end;
  723.  
  724.                     iQuit: 
  725.                         finished := true;
  726.                 end; {case item}
  727.             mEdit: 
  728.                 ;
  729.         end; {case menu}
  730.         HiliteMenu(0);
  731.     end; {HandleMenus}
  732.  
  733.     procedure HandleClick (var wherePtr: Point);
  734.     begin
  735.         if (gameInProgress) then
  736.             begin
  737.                 if (selectingMultiples) then
  738.                     SelectMultiples(wherePtr)
  739.                 else
  740.                     PlaceCards(wherePtr);
  741.             end;
  742.     end;
  743.  
  744.     procedure EventLoop;
  745.         var
  746.             e: EventRecord;
  747.             window: WindowPtr;
  748.             part: Integer;
  749.     begin
  750.         repeat
  751.             begin
  752. {$IFC UNDEFINED THINK_PASCAL}
  753.                 SetCursor(qd.arrow);
  754. {$ELSEC}
  755.                 SetCursor(arrow);
  756. {$ENDC}
  757.                 if WaitNextEvent(everyEvent, e, -1, nil) then
  758.                     case e.what of
  759.                         keyDown: 
  760.                             if BAnd(e.modifiers, cmdKey) <> 0 then
  761.                                 HandleMenus(MenuKey(Char(BAnd(e.message, charCodeMask))));
  762.                         mouseDown: 
  763.                             begin
  764.                                 part := FindWindow(e.where, window);
  765.                                 case part of
  766.                                     inDrag: 
  767. {$IFC UNDEFINED THINK_PASCAL}
  768.                                         DragWindow(window, e.where, qd.screenBits.bounds);
  769. {$ELSEC}
  770.                                     DragWindow(window, e.where, screenBits.bounds);
  771. {$ENDC}
  772.  
  773.                                     inMenuBar: 
  774.                                         HandleMenus(MenuSelect(e.where));
  775.  
  776.                                     inSysWindow: 
  777.                                         SystemClick(e, window);
  778.  
  779.                                     inContent: 
  780.                                         begin
  781.                                             SetPort(window);
  782.                                             GlobalToLocal(e.where);
  783.                                             HandleClick(e.where);
  784.                                         end;
  785.                                 end; {case part}
  786.                             end;
  787.  
  788.                         updateEvt: 
  789.                             begin
  790.                                 BeginUpdate(WindowPtr(e.message));
  791.                                 SetPort(WindowPtr(e.message));
  792.                                 RedrawWindow;
  793.                                 EndUpdate(WindowPtr(e.message));
  794.                             end;
  795.                     end; {case what}
  796.             end; {repeat}
  797.         until finished;
  798.     end; {EventLoop}
  799.  
  800. {Main program}
  801. begin
  802.     Initialize;
  803.  
  804.     RetrieveResources;
  805.  
  806.     EmptyGrid;
  807.  
  808.     repeat
  809.         EventLoop;
  810.     until finished;
  811. end.